package pl.iachoo.ctl.tabory.ui.editors.vagons.composites;

import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;

import pl.iachoo.ctl.tabory.dao.api.services.IVagonService;
import pl.iachoo.ctl.tabory.dao.data.vo.CompositionVO;
import pl.iachoo.ctl.tabory.dao.data.vo.VagonVO;
import pl.iachoo.ctl.tabory.dao.hibernate.services.ServiceManager;
import pl.iachoo.ctl.tabory.ui.base.EditorStateSL;
import pl.iachoo.ctl.tabory.ui.base.masterdetail.AbstractMasterSectionPart;
import pl.iachoo.ctl.tabory.ui.editors.vagons.VagonSelection;
import pl.iachoo.ctl.tabory.ui.properties.Messages;
import pl.iachoo.ctl.tabory.ui.selection.ISelectionListener;

public class VagonMasterSectionPart extends
		AbstractMasterSectionPart<VagonSelection> {

	private final static Logger logger = Logger
			.getLogger(VagonMasterSectionPart.class);

	public enum AvailableColumnsSL {
		COLUMN_VAGON_NAME, COLUMN_COMPOSITION_NAME
	};

	private boolean isToolBarVisible;
	private boolean isFilterVisible;

	private Set<AvailableColumnsSL> columnSet;

	private FilterCompositionId filterCompositionId;
	private FilterVagonId filterVagonId;
	private Text filterVagonName;
	private Text filterVagonComposition;
	private Section filterSection;

	private ISelectionListener<VagonSelection> selectionListener;

	public VagonMasterSectionPart(Composite parent, FormToolkit toolkit,
			int style, String sectionName, boolean isToolBarVisible,
			boolean isFilterVisible, Set<AvailableColumnsSL> columnSet) {
		super(parent, toolkit, style, sectionName);
		this.isFilterVisible = isFilterVisible;
		this.isToolBarVisible = isToolBarVisible;
		this.columnSet = columnSet;
		initGui(parentSection, toolkit);
		postInitGui(parentSection, toolkit);
		initActions();
	}

	@Override
	public VagonSelection getSelection() {
		return selection;
	}

	@Override
	public void setSelection(VagonSelection selection) {
		this.selection = selection;
		refreshToolBar();
		if (selection.getEditorState().equals(EditorStateSL.CLEAN)) {
			setEnabled(true);
		} else {
			setEnabled(false);
		}
		tableViewer.setInput(selection.getListVagons());
	}

	@Override
	public void addSelectionListener(ISelectionListener<VagonSelection> listner) {
		this.selectionListener = listner;
	}

	@Override
	public void removeSelectionListener(
			ISelectionListener<VagonSelection> listner) {
	}

	@Override
	protected void initGui(Section parentSection, FormToolkit toolkit) {
		toolBar = getToolBar(parentSection, toolkit);
		parentSection.setTextClient(toolBar);
		toolBar.setVisible(isToolBarVisible);

		Composite container = toolkit.createComposite(parentSection);
		GridLayoutFactory.fillDefaults().numColumns(1).applyTo(container);
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
				.grab(true, true).applyTo(container);

		parentSection.setClient(container);
		tableViewer = new TableViewer(container, SWT.BORDER
				| SWT.FULL_SELECTION);
		table = tableViewer.getTable();
		table.setHeaderVisible(true);
		toolkit.paintBordersFor(table);
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
				.grab(true, true).applyTo(table);

		if (columnSet.contains(AvailableColumnsSL.COLUMN_VAGON_NAME)) {
			TableColumn columnVagonId = new TableViewerColumn(tableViewer,
					SWT.NONE).getColumn();
			columnVagonId.setWidth(100);
			columnVagonId.setText(Messages
					.getString("vagons.editor.master.table.col0"));
		}

		if (columnSet.contains(AvailableColumnsSL.COLUMN_COMPOSITION_NAME)) {
			TableColumn columnCompositionId = new TableViewerColumn(
					tableViewer, SWT.NONE).getColumn();
			columnCompositionId.setWidth(100);
			columnCompositionId.setText(Messages
					.getString("vagons.editor.master.table.col1"));
		}

		tableViewer.setLabelProvider(new TableLabelProvider());
		tableViewer.setContentProvider(new TableContentProvider());
		tableViewer.setSorter(new TableViewerSorter());
		tableViewer.addFilter(filterCompositionId = new FilterCompositionId());
		tableViewer.addFilter(filterVagonId = new FilterVagonId());

		filterSection = toolkit.createSection(container, Section.TWISTIE
				| Section.TITLE_BAR);
		GridLayoutFactory.fillDefaults().numColumns(1).margins(5, 5)
				.applyTo(filterSection);
		toolkit.paintBordersFor(filterSection);
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
				.grab(false, false).applyTo(filterSection);

		Composite filterComposite = toolkit.createComposite(filterSection);
		filterSection.setText(Messages.getString("common.filter"));
		toolkit.paintBordersFor(filterComposite);
		filterSection.setClient(filterComposite);
		GridLayoutFactory.fillDefaults().numColumns(2).margins(3, 3)
				.applyTo(filterComposite);
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
				.grab(false, false).applyTo(filterComposite);

		Label filterVagonNameLabel = toolkit.createLabel(filterComposite,
				Messages.getString("vagons.editor.filter.vagonname"));
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
				.grab(true, true).applyTo(filterVagonNameLabel);
		filterVagonName = toolkit.createText(filterComposite, "");
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
				.hint(100, SWT.DEFAULT).grab(true, true)
				.applyTo(filterVagonName);
		Label filterVagonCompositionLabel = toolkit.createLabel(
				filterComposite,
				Messages.getString("vagons.editor.filter.compositionname"));
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
				.grab(true, true).applyTo(filterVagonCompositionLabel);
		filterVagonComposition = toolkit.createText(filterComposite, "");
		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL)
				.hint(100, SWT.DEFAULT).grab(true, true)
				.applyTo(filterVagonComposition);
		toolkit.adapt(filterComposite, true, true);

		filterSection.setVisible(isFilterVisible);
	}

	@Override
	public void setEnabled(boolean isEnabled) {
		super.setEnabled(isEnabled);
		filterSection.setEnabled(isEnabled);
	}

	@Override
	protected void refreshToolBar() {
		if (selection.getSelectedVagon() == null) {
			toolItemNew.setEnabled(true);
			toolItemEdit.setEnabled(false);
			toolItemDelete.setEnabled(false);
		} else {
			toolItemNew.setEnabled(true);
			toolItemEdit.setEnabled(true);
			toolItemDelete.setEnabled(true);
		}
	}

	@Override
	protected void postInitGui(Section parentSection, FormToolkit toolkit) {
	}

	@Override
	protected void initActions() {
		filterVagonComposition.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(org.eclipse.swt.events.KeyEvent e) {
				filterCompositionId.setPattern(filterVagonComposition.getText());
				tableViewer.refresh();
			}
		});
		filterVagonName.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(org.eclipse.swt.events.KeyEvent e) {
				filterVagonId.setPattern(filterVagonName.getText());
				tableViewer.refresh();
			}
		});
		toolItemNew.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				selection.setEditorState(EditorStateSL.NEW);
				selection.setSelectedVagon(null);
				selectionListener.selectionChanged(selection);
			}
		});
		toolItemEdit.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				selection.setEditorState(EditorStateSL.EDITING);
				selectionListener.selectionChanged(selection);
			}
		});
		toolItemDelete.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				try {
					IVagonService vagonService = ServiceManager
							.getVagonService();
					VagonVO selectedVagon = selection.getSelectedVagon();
					boolean openConfirm = MessageDialog.openConfirm(
							getSection().getShell(),
							Messages.getString("vagons.editor.questions.delete.title"),
							Messages.getString("vagons.editor.questions.delete.message"));
					if (openConfirm) {
						vagonService.deleteVagon(selectedVagon);
						selection.setListVagons(vagonService.getListAllVagons());
						selection.setSelectedVagon(null);
						selectionListener.selectionChanged(selection);
					}
				} catch (Exception ex) {
					logger.error(ex.getMessage(), ex);
				}
			}
		});
		tableViewer
				.addSelectionChangedListener(new ISelectionChangedListener() {
					@Override
					public void selectionChanged(SelectionChangedEvent event) {
						logger.debug("Table selection changed");
						IStructuredSelection tableSelection = (IStructuredSelection) event
								.getSelection();
						VagonVO selectedVagon = (VagonVO) tableSelection
								.getFirstElement();
						selection.setSelectedVagon(selectedVagon);
						selectionListener.selectionChanged(selection);
					}
				});
	}

	private class TableLabelProvider extends LabelProvider implements
			ITableLabelProvider {

		@Override
		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		@Override
		public String getColumnText(Object element, int columnIndex) {
			VagonVO vagon = (VagonVO) element;
			switch (columnIndex) {
			case 0:
				return vagon.getInternalId();
			case 1:
				CompositionVO composition = vagon.getComposition();
				if (composition != null) {
					return composition.getInternalId();
				}
			default:
				return "";
			}
		}

	}

	private class TableContentProvider implements IStructuredContentProvider {

		@Override
		public void dispose() {
		}

		@Override
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}

		@Override
		@SuppressWarnings("unchecked")
		public Object[] getElements(Object inputElement) {
			List<VagonVO> listVagons = (List<VagonVO>) inputElement;
			return listVagons.toArray();
		}

	}
	
	private class TableViewerSorter extends ViewerSorter {
		@Override
		public int compare(Viewer viewer, Object e1, Object e2) {
			VagonVO v1 =(VagonVO)e1;
			VagonVO v2 =(VagonVO)e2;
			return super.compare(viewer, v1.getInternalId(), v2.getInternalId());
		}
	}

	private class FilterVagonId extends ViewerFilter {

		private String patter;

		public void setPattern(final String pattern) {
			this.patter = pattern;
		}

		@Override
		public boolean select(Viewer viewer, Object parentElement,
				Object element) {
			if (patter == null || patter.length() == 0) {
				return true;
			}
			VagonVO vagon = (VagonVO) element;
			if (vagon.getInternalId().contains(patter)) {
				return true;
			}
			return false;
		}
	}

	private class FilterCompositionId extends ViewerFilter {

		private String patter;

		public void setPattern(final String pattern) {
			this.patter = pattern;
		}

		@Override
		public boolean select(Viewer viewer, Object parentElement,
				Object element) {
			if (patter == null || patter.length() == 0) {
				return true;
			}
			VagonVO vagon = (VagonVO) element;
			if (vagon.getComposition().getInternalId().contains(patter)) {
				return true;
			}
			return false;
		}
	}

}
